﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web.Razor;
using System.Web.Razor.Generator;
using System.Web.Razor.Parser;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;

namespace STX.Core.TemplateEngin
{
    public class RazorCompiler
    {
        public Type compile<T>()
        {
            var key = Guid.NewGuid().ToString("N");
            var className = string.Format("C_{0}", key);
            var baseType = typeof(TemplateBase<>).MakeGenericType(typeof(T));

            var template = "hello my razor view engin";

            var host = new RazorEngineHost(new CSharpRazorCodeLanguage(), () => new HtmlMarkupParser())
            {

                DefaultBaseClass = baseType.FullName,
                DefaultClassName = className,
                DefaultNamespace = "SP.Core.TemplateEngin.dynamic",
                GeneratedClassContext =
                    new GeneratedClassContext("Execute", "Write", "WriteLiteral", "WriteTo",
                                              "WriteLiteralTo",
                                              "SP.Core.TemplateEngin.TemplateBase")

            };

            host.NamespaceImports.Add("System");
            host.NamespaceImports.Add("SP.Core.TemplateEngin");


            CodeCompileUnit code;
            using (var reader = new StreamReader(@"I:\work\ST\STX.Web\templates\default\Account\test.cshtml"))
            {
                var generatedCode = new RazorTemplateEngine(host).GenerateCode(reader);
                code = generatedCode.GeneratedCode;
            }

            var @params = new CompilerParameters
            {
                IncludeDebugInformation = false,
                TempFiles = new TempFileCollection(AppDomain.CurrentDomain.DynamicDirectory),
                CompilerOptions = "/target:library /optimize",
                GenerateInMemory = false
            };

            var assemblies = AppDomain.CurrentDomain
               .GetAssemblies()
               .Where(a => !a.IsDynamic)
               .Select(a => a.Location)
               .ToArray();

            @params.ReferencedAssemblies.AddRange(assemblies);

            var provider = new CSharpCodeProvider();
            var compiled = provider.CompileAssemblyFromDom(@params, code);

            if (compiled.Errors.Count > 0) {
                var compileErrors = string.Join("\r\n", compiled.Errors.Cast<object>().Select(o => o.ToString()));
                throw new ApplicationException("Failed to compile Razor:" + compileErrors);
            }

            return compiled.CompiledAssembly.GetType("SP.Core.TemplateEngin.dynamic." + className);
        }
    }
}
